﻿#include "lineEndChanger.h"
#include "Utils.h"
#include "CmdParamHandler.h"

const string lineEndChanger::ERR_PARAMETER 	= "参数有误，请检查你的参数";
const string lineEndChanger::ERR_IN_FILE 	= "输入文件有误，请检查";
const string lineEndChanger::ERR_OUT_FILE	= "输出文件有误，请检查";
const string lineEndChanger::ERR_SYS_PARA 	= "目标类型参数错误，请检查";

const string lineEndChanger::INFO_START = "==========欢迎使用换行符转换工具===========\n你可以使用命令行参数来集成这个工具到批处理或shell中\n具体参数请输入 -? 查看";
const string lineEndChanger::INFO_INIT  = "==========初始化文件和输出类型=============";	
const string lineEndChanger::INFO_CONV  = "==========转换中==========================";
const string lineEndChanger::INFO_SELE  = "==========请指定文件和输出类型=============";
const string lineEndChanger::INFO_DONE  = "==========转换完成========================";
const string lineEndChanger::INFO_QUIT  = "==========退出程序========================";
const string lineEndChanger::INFO_OVER  = "==========再见！==========================";
const string lineEndChanger::INFO_PARA  = "参数表：  [-y] 输入文件  输出文件  输出类型\n输出类型：win , mac , unix \n -?:查看参数表\n -y:覆盖存在的文件";

const char* lineEndChanger::LINE_FEED_MAC	= "\r";
const char* lineEndChanger::LINE_FEED_WIN	= "\r\n";	
const char* lineEndChanger::LINE_FEED_UNIX	= "\n";

int lineEndChanger::getStatus(){
	return status;
}

int lineEndChanger::setStatus(int st){
	lastStatus = status;
	status = st;
	return status;
}
int lineEndChanger::getLastStatus(){
	return lastStatus;
}	
bool lineEndChanger::fileInLoad(){
	if(sizeof(fileNameIn)==0)
	{
		return false;
	}
#ifdef OLD_IO
	fileIn.open(fileNameIn.c_str(),ios::binary|ios::in|ios::_Nocreate|ios::ate);
#else
	fileIn.open(fileNameIn.c_str(),ios::binary|ios::in|/*ios::_Nocreate|*/ios::ate);
#endif
	if(fileIn){
		return true;
	}
	else
	{
		errStr += Utils::strAddLN(lineEndChanger::ERR_IN_FILE);
		return false;
	}
}

bool lineEndChanger::fileOutLoad(){
	if(sizeof(fileNameOut)==0)
		return false;
	//判断文件是否存在
	if(Utils::fileExist(fileNameOut.c_str())){
		string input;
		if(!overWriteFlag){
			if(isByCMD){
				cout << "文件已经存在，是否覆盖？(输入y覆盖，输入其他退出)" << endl;
			}else{
				cout << "文件已经存在，是否覆盖？(输入y覆盖，输入其他返回)" << endl;
			}
			cin >> input;
		}
		if(overWriteFlag||input=="y"){
			fileOut.open(fileNameOut.c_str(),ios::binary|ios::out);
		}else{
			return false;
		}
	}else{
#ifdef OLD_IO
		fileOut.open(fileNameOut.c_str(),ios::binary|ios::out|ios::_Noreplace);
#else
		fileOut.open(fileNameOut.c_str(),ios::binary|ios::out/*|ios::_Noreplace*/);
#endif
	}
	if(fileOut){
		return true;
	}
	else
	{
		errStr += Utils::strAddLN(lineEndChanger::ERR_OUT_FILE);
		return false;
	}
}


bool lineEndChanger::fileInOutLoad(){
	//判断文件是否存在
	if(Utils::fileExist(fileNameIn.c_str())){
		string input;
		if(!overWriteFlag){
			if(isByCMD){
				cout << "文件已经存在，是否覆盖？(输入y覆盖，输入其他退出)" << endl;
			}else{
				cout << "文件已经存在，是否覆盖？(输入y覆盖，输入其他返回)" << endl;
			}
			cin >> input;
		}
		if(overWriteFlag||input=="y"){
			fileInOut.open(fileNameOut.c_str(),ios::binary|ios::out|ios::in|ios::ate);
		}else{
			return false;
		}
	}else{
		return false;
	}
	if(fileInOut){
		return true;
	}else{
		errStr += Utils::strAddLN(lineEndChanger::ERR_OUT_FILE);
		return false;
	}
}



bool lineEndChanger::lecInit(){
	bool result = true;
	inOutFlag = false;
	//检查是否同一个文件,是的话进入读写模式
	if(!(sizeof(fileNameOut)==0)&&(fileNameOut==fileNameIn)){
		inOutFlag = true;
		if(!fileInOutLoad()){
			result = false;
		}
	}
	//检查输入文件
	else if(!fileInLoad()){
		result = false;
	}
	//检查输出文件 如果输入文件为空就不创建输出文件了，所以用else
	else if(!fileOutLoad()){
		result = false;
	}
	//检查目标类型
	if(outType <= 0){
		errStr += Utils::strAddLN(lineEndChanger::ERR_SYS_PARA);
		result = false;
	}
	return result;
}	

bool lineEndChanger::lecConvert(){
	bool result = true;
	//先将输入复制到缓冲区
	char *buffer;
	long size;
	if(inOutFlag){
		size = fileInOut.tellg();
		fileInOut.seekg(0,ios::beg);	
	}else{
		size = fileIn.tellg();
		fileIn.seekg(0,ios::beg);	
	}										//最后一个符号不包括结尾符
	buffer = new char[size + 1];			//增加一个结尾符的位置
	if(inOutFlag){
		fileInOut.read(buffer,size);	
	}else{
		fileIn.read(buffer,size);
	}
	buffer[size] = '\0';					//增加一个结尾符
	if(inOutFlag){
		fileInOut.seekg(0,ios::beg);
	}else{
		fileIn.close();
	}
	cout << "文件已经读入缓冲区，开始转换换行符" <<endl;
	//先尝试用string来解决
	string content(buffer);
#ifdef DEBUG
	cout << "========content before convert======" << endl;
	cout << content << endl;
#endif
	switch(outType){
	case lineEndChanger::SYS_MAC:
		convertToMac(content);
		break;
	case lineEndChanger::SYS_WINDOWS:
		convertToWin(content);
		break;
	case lineEndChanger::SYS_UNIX:
		convertToUnx(content);
		break;
	}
	if(inOutFlag){
		fileInOut << content;
		fileInOut.close();
	}else{
		fileOut << content;
		fileOut.close();
	}
	//完成
	delete[] buffer;
	return result;
}

string& lineEndChanger::convertToMac(string &str){

	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_WIN,lineEndChanger::LINE_FEED_MAC);
	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_UNIX,lineEndChanger::LINE_FEED_MAC);

#ifdef DEBUG
	cout << str << endl;
#endif
	return str;
}

string& lineEndChanger::convertToWin(string &str){

	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_WIN,lineEndChanger::LINE_FEED_UNIX);
	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_MAC,lineEndChanger::LINE_FEED_UNIX);
	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_UNIX,lineEndChanger::LINE_FEED_WIN);

#ifdef DEBUG
	cout << str << endl;
#endif
	return str;
}

string& lineEndChanger::convertToUnx(string &str){
	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_WIN,lineEndChanger::LINE_FEED_UNIX);
	Utils::strReplaceAll(str,lineEndChanger::LINE_FEED_MAC,lineEndChanger::LINE_FEED_UNIX);

#ifdef DEBUG
	cout << str << endl;
#endif
	return str;
}

void lineEndChanger::clearErr(){
	errStr = string("");
}	

void lineEndChanger::printInfo(){
	switch(getStatus()){
	case lineEndChanger::STA_START:
		cout << lineEndChanger::INFO_START << endl;
		break;
	case lineEndChanger::STA_INIT:
		cout << lineEndChanger::INFO_INIT << endl;
		break;
	case lineEndChanger::STA_SELE:
		cout << lineEndChanger::INFO_SELE << endl;
		break;
	case lineEndChanger::STA_CONV:
		cout << lineEndChanger::INFO_CONV << endl;
		break;
	case lineEndChanger::STA_ERR:
		cout << errStr << endl;
		break;
	case lineEndChanger::STA_DONE:
		cout << lineEndChanger::INFO_DONE << endl;
		break;
	case lineEndChanger::STA_QUIT:
		cout << lineEndChanger::INFO_QUIT << endl;
		break;
	default:
		cout << errStr << endl;
		break;
	}
}

bool lineEndChanger::lecSelect(){
	bool result = true;
	bool outTypeFlag = true;
	cout << "输入你要读取的文件名:" << endl;
	cin >> fileNameIn;
	cout << "输入你要输出的文件名:" << endl;
	cin >> fileNameOut;

	do{
		cout << "输入编号选择你要转换成的类型" << endl;
		cout << "1.MAC		//<CR>    	:\\r" << endl;
		cout << "2.windows	//<CRLF>	:\\r\\n" << endl;
		cout << "3.unix		//<LF>		:\\n"	<<endl;	
		cin >> outType;
		if(!cin){
			outTypeFlag = false;
			cin.clear();
			cin.sync();
			cout << "请输入编号来选择！" << endl;
		}else
			if(outType < lineEndChanger::SYS_MAC || outType > lineEndChanger::SYS_UNIX){
				outTypeFlag = false;
				outType = lineEndChanger::SYS_NONE;
				cout << "请输入正确的编号！" << endl;
			}else {
				outTypeFlag = true;
			}
	} while (!outTypeFlag);
	return result;
}


bool lineEndChanger::lecDone(){
	bool result = true;
	string input;
	cout << "转换完成，是否继续转换？(输入y继续，其他键退出)" << endl;
	cin >> input;
	if(input!="y"){
		result = false;
	}
	return result;
}

bool lineEndChanger::lecErrHandle(){
	clearErr();
	bool result = true;
	string input;
	cout << "是否继续？输入y重来，输入其他退出" << endl;
	cin >> input;
	if(input!="y"){
		setStatus(lineEndChanger::STA_QUIT);
		return result;
	}


	/*********再初始化*****************/
	if(fileIn){
		fileIn.close();
	}
	if(fileOut){
		fileOut.close();
	}
	if(fileInOut){
		fileInOut.close();
	}
	outType = lineEndChanger::SYS_NONE;
	/*********再初始化*****************/


	switch(getLastStatus()){
	case lineEndChanger::STA_START:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_INIT:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_SELE:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_CONV:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_ERR:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_DONE:
		setStatus(lineEndChanger::STA_START);
		break;
	case lineEndChanger::STA_QUIT:
		setStatus(lineEndChanger::STA_QUIT);
		break;
	default:
		setStatus(lineEndChanger::STA_QUIT);
		break;
	}
	return result;
}

bool lineEndChanger::lecStart(int argc,char **args){
	bool result = true;
#ifdef DEBUG
	cout << "************DEBUG INFO:ARGS*****************"<< endl;
	cout << "argc:" << argc << endl;
	cout << "args:" << endl;
	for(int i = 0 ;i!= argc; ++i){
		cout << args[i] << endl;
	}
	cout << "************DEBUG INFO:ARGS*****************"<< endl;
#endif
	//有参数，控制台模式flag置为true
	if (argc > 1) {
		isByCMD = true;
		vector<string> opts(2);
		opts[0] = "-y";
		opts[1] = "-?";
		CmdParamHandler cph(argc,args,opts,5);
#ifdef DEBUG
		cout << "************DEBUG INFO:CPH STATUS*****************"<< endl;
		cout << "opts size: "<<opts.size() << endl;
		cout << "maxParas: "<<cph.maxParas << endl;
		cout << "maxPrios: "<<cph.maxPrios << endl;
		cout << "optBeg: "<<cph.optBeg << endl;
		cout << "************DEBUG INFO:CPH STATUS*****************"<< endl;
		system("pause");
#endif
		if(cph.checkLegal()){
			if(cph.hasThisOptPara(string("-?"))){
				result = false;
				errStr += Utils::strAddLN(lineEndChanger::INFO_PARA);
				return result;
			}
			if(cph.hasThisOptPara(string("-y"))){
				overWriteFlag = true;
			}else{
				overWriteFlag = false;
			}
			fileNameIn = cph.paraPrioX(1);
			fileNameOut =  cph.paraPrioX(2);
			string type =  cph.paraPrioX(3);
			if (type == "win") {
				outType = lineEndChanger::SYS_WINDOWS;
			} else if (type == "mac") {
				outType = lineEndChanger::SYS_MAC;
			} else if (type == "unix") {
				outType = lineEndChanger::SYS_UNIX;
			} else {
				outType = lineEndChanger::SYS_NONE;
				result = false;
				errStr += Utils::strAddLN(lineEndChanger::ERR_SYS_PARA);
				errStr += Utils::strAddLN(lineEndChanger::INFO_PARA);
			}
		}else{
			result = false;
			errStr += Utils::strAddLN(lineEndChanger::ERR_PARAMETER);
			errStr += Utils::strAddLN(lineEndChanger::INFO_PARA);
		}
	}
	return result;
}	

lineEndChanger::~lineEndChanger(void)
{
}

